package tk.hongbo.mpen;

import static tk.hongbo.mpen.Sort.FILE_CACHE_DIR;
import static tk.hongbo.mpen.Sort.FILE_NAME_DATA;
import static tk.hongbo.mpen.Sort.FILE_NAME_RESULT;

import android.content.Context;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

@RunWith(AndroidJUnit4.class)
public class SortTest {

    private static final int s1 = 0, s2 = 560, s3 = 1232, s4 = 8888, s5 = 9999; //验证文件下标
    private static final int numCount = 100; //总数
    private static int a1, a2, a3, a4, a5; //指定位置数字
    private static int aMax = -1, aMin = -1; //指定位置数字

    Sort sort = new Sort();

    /**
     * 创建测试数据文件
     */
    @Before
    public void createData() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        File dataFile = new File(appContext.getFilesDir(), Sort.FILE_NAME_DATA);
        if (dataFile.exists()) {
            dataFile.delete();
        }
        DataOutputStream out = null;
        try {
            dataFile.createNewFile();
            out = new DataOutputStream(new FileOutputStream(dataFile, true));

            //写测试数据
            Random random = new Random();
            for (int i = 0; i < numCount; i++) {
                int number = random.nextInt(Integer.MAX_VALUE);
                out.writeInt(number);
                switch (i) {
                    case s1:
                        a1 = number;
                        break;
                    case s2:
                        a2 = number;
                        break;
                    case s3:
                        a3 = number;
                        break;
                    case s4:
                        a4 = number;
                        break;
                    case s5:
                        a5 = number;
                        break;
                }
                //记录最大值
                if (aMax == -1 || number > aMax) {
                    aMax = number;
                }
                //记录最小值
                if (aMin == -1 || number < aMin) {
                    aMin = number;
                }
            }
            System.out.println("Max：" + aMax + ",Min：" + aMin);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 验证数据读取是否正常
     */
    @Ignore
    @Test
    public void checkData() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        File dataFile = new File(appContext.getFilesDir(), FILE_NAME_DATA);
        if (!dataFile.exists()) {
            return;
        }
        DataInputStream in = null;
        try {
            in = new DataInputStream(new FileInputStream(dataFile));
            int sequence = -1;
            while (in.available() > 0) {
                sequence++;
                int number = in.readInt();
                switch (sequence) {
                    case s1:
                        assert a1 == number;
                        break;
                    case s2:
                        assert a2 == number;
                        break;
                    case s3:
                        assert a3 == number;
                        break;
                    case s4:
                        assert a4 == number;
                        break;
                    case s5:
                        assert a5 == number;
                        break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 创建输出文件是否正常
     */
    @Ignore
    @Test
    public void testCreateResultFile() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        File outFile = sort.createResultFile(appContext);
        assert outFile.exists();
        assert outFile.length() == 0;
        //测试数据清理
        outFile.delete();
    }

    /**
     * 创建输出文件是否正常（之前有文件情况）
     */
    @Ignore
    @Test
    public void testCreateResultFileOld() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        File oldFile = new File(appContext.getFilesDir(), FILE_NAME_RESULT);
        if (!oldFile.exists()) {
            try {
                oldFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        File outFile = sort.createResultFile(appContext);
        assert outFile.exists();
        assert outFile.length() == 0;
        //测试数据清理
        outFile.delete();
    }

    /**
     * 清空临时文件目录是否正常
     */
    @Ignore
    @Test
    public void testClearCache() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        sort.clearCache(appContext);

        File cacheFile = new File(appContext.getCacheDir(), FILE_CACHE_DIR);
        assert !cacheFile.exists();
    }

    /**
     * 创建临时文件目录是否正常
     */
    @Ignore
    @Test
    public void testCreateCacheDir() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        File cacheFile = sort.createCacheDir(appContext);
        assert cacheFile.exists();
        assert cacheFile.isDirectory();
        assert cacheFile.listFiles().length == 0;
        //测试数据清理
        cacheFile.delete();
    }

    /**
     * 分段文件写入是否正常
     */
    @Ignore
    @Test
    public void testWriteItemFile() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        ArrayList<Integer> testDate = new ArrayList<>();
        testDate.add(6);
        testDate.add(2);
        testDate.add(777);
        testDate.add(9);
        testDate.add(3);
        testDate.add(11);
        testDate.add(666);
        sort.writeItemFile(appContext.getCacheDir(), "test", testDate);

        //文件存在
        File file = new File(appContext.getCacheDir(), "test");
        assert file.exists();

        //文件内容判断
        DataInputStream in = null;
        try {
            in = new DataInputStream(new FileInputStream(file));
            int sequence = -1;
            while (in.available() > 0) {
                sequence++;
                int num = in.readInt();
                switch (sequence) {
                    case 0: {
                        assert num == 2;
                        break;
                    }
                    case 1: {
                        assert num == 3;
                        break;
                    }
                    case 2: {
                        assert num == 6;
                        break;
                    }
                    case 3: {
                        assert num == 9;
                        break;
                    }
                    case 4: {
                        assert num == 11;
                        break;
                    }
                    case 5: {
                        assert num == 666;
                        break;
                    }
                    case 6: {
                        assert num == 777;
                        break;
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //测试数据清理
            if (file.exists()) {
                file.delete();
            }
        }
    }

    /**
     * 分段写入文件是否正常
     */
    @Ignore
    @Test
    public void testReadAndItemWrite() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        File dataFile = new File(appContext.getFilesDir(), Sort.FILE_NAME_DATA);
        File cacheFile = new File(appContext.getCacheDir(), Sort.FILE_CACHE_DIR);
        if (!cacheFile.exists()) {
            cacheFile.mkdir();
        }
        sort.readAndItemWrite(dataFile, cacheFile);

        assert cacheFile.isDirectory();
        assert cacheFile.listFiles().length > 0;

        DataInputStream in = null;
        try {
            in = new DataInputStream(new FileInputStream(cacheFile.listFiles()[0]));
            int sum = -1;
            while (in.available() > 0) {
                int lineSum = in.readInt();
                assert lineSum > sum;
                sum = lineSum;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //数据清理
            dataFile.delete();
            sort.clearCache(appContext);
        }
    }

    @Ignore
    @Test
    public void testOutput() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        File resultFile = new File(appContext.getFilesDir(), FILE_NAME_RESULT);

        File cacheFile = new File(appContext.getCacheDir(), Sort.FILE_CACHE_DIR);
        if (!cacheFile.exists()) {
            cacheFile.mkdir();
        }

        //分段写入文件
        File dataFile = new File(appContext.getFilesDir(), Sort.FILE_NAME_DATA);
        sort.readAndItemWrite(dataFile, cacheFile);

        //合并文件
        DataInputStream in = null;
        try {
            sort.output(resultFile, cacheFile, numCount);

            //文件检查
            in = new DataInputStream(new FileInputStream(resultFile));
            int sum = -1;
            while (in.available() > 0) {
                int lineSum = in.readInt();
                assert lineSum > sum;
                sum = lineSum;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //数据清理
            sort.clearCache(appContext);
            resultFile.delete();
        }
    }

    @Test
    public void testLargerFileSort() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        File dataFile = new File(appContext.getFilesDir(), Sort.FILE_NAME_DATA);

        //输出内容检查
        DataInputStream in = null;
        try {
            if (!dataFile.exists()) {
                dataFile.createNewFile();
            }
            sort.largeFileSort(appContext);

            //输出文件检查
            File outFile = new File(appContext.getFilesDir(), Sort.FILE_NAME_RESULT);
            assert outFile.exists();
            assert outFile.length() > 0;

            in = new DataInputStream(new FileInputStream(outFile));
            int countNum = 0;
            int sum = -1;
            while (in.available() > 0) {
                int lineSum = in.readInt();
                assert lineSum > sum;
                sum = lineSum;
                countNum++;
            }
            assert countNum == numCount;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}